package com.zf.museum.service.impl;

import com.zf.museum.bean.GetResult;
import com.zf.museum.bean.Msg;
import com.zf.museum.bean.Question;
import com.zf.museum.bean.Result;
import com.zf.museum.model.*;
import com.zf.museum.repository.*;
import com.zf.museum.service.*;
import com.zf.museum.shiro.CustomizedToken;
import com.zf.museum.shiro.LoginType;
import com.zf.museum.utils.Md5Util;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Set;

@Service
public class UserServiceImpl implements UserService{

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private MessageRepository messageRepository;
    @Autowired
    private StateRepository stateRepository;
    @Autowired
    private TfngService tfngService;
    @Autowired
    private MultiChoicesService multiChoicesService;
    @Autowired
    private SingleChoiceService singleChoiceService;

    private static final String USER_LOGIN_TYPE = LoginType.USER.toString();

    @Override
    public Result login(String name, String openId) {

        Result result = GetResult.success();
        Subject currentUser = SecurityUtils.getSubject();
        /*添加用户*/
        addUser(name, openId);
        if (!currentUser.isAuthenticated()) {
            /*指明登录类型为普通用户登录(在授权时使用)*/
            currentUser.getSession().setAttribute("loginType", USER_LOGIN_TYPE);
            CustomizedToken customizedToken = new CustomizedToken(openId, openId, USER_LOGIN_TYPE);
            //暂时指定为false
            customizedToken.setRememberMe(false);
            try {
                currentUser.login(customizedToken);
            } catch (Exception e) {
                e.printStackTrace();
                return GetResult.fail();
            }
        }

        return result;
    }

    @Override
    public Result updateName(String name, String openId) {

        User user = userRepository.getUserByOpenId(openId);

        try {
            user.setName(name);
            userRepository.save(user);
        } catch (Exception e) {
            e.printStackTrace();
            return GetResult.fail();
        }
        return GetResult.success();
    }

    @Override
    public User getUserByOpenId(String openId) {

        sort();
        return userRepository.getUserByOpenId(openId);
    }

    @Override
    public Set<User> getTop10User(String openId) {

        sort();
        Set<User> users = userRepository.getTop10ByOrderByRankAsc();
        User user = userRepository.getUserByOpenId(openId);
        users.add(user);
        return users;
    }

    private void sort() {

        Set<User> users = userRepository.getAllByOrderByScoreDesc();
        int rank = 0;
        for (User user: users
                ) {
            ++rank;
            user.setRank(rank);
            userRepository.save(user);
        }
    }

    private void addUser(String name, String openId) {

        User user = userRepository.getUserByOpenId(openId);
        /*使用md5加密*/
        String password = Md5Util.getPassword(openId, openId);;
        /*第一次登录*/
        if (user == null) {
            user = new User();
            user.setOpenId(openId);
            user.setPassword(password);
            user.setScore(0);
            user.setRank(0);
            user.setState(1);
            user.setGrade("");
            user.setName(name);
            Role role = roleRepository.getRoleByRole("user");
            user.setRole(role);
            userRepository.save(user);
        }

    }

    @Override
    public Result judge(Question question) {

        Result<Msg> result = GetResult.success();
        String openId = question.getOpenId();
        /*获取当前答题时间*/
        Date date2 = new Date();
        Date date1 = null;
        try {
            /*1.获取用户信息*/
            User user = userRepository.getUserByOpenId(openId);
            /*2.根据闯关状态获取关卡提示信息*/
            Message message = messageRepository.getMessageByNumber(user.getState());
            Msg msg = new Msg();
            msg.setPass(false);
            /*3.获取闯关状态*/
            State state = stateRepository.getStateByOpenId(openId);
            /*4.判断该用户是否第一次答题*/
            if (state == null){
                state = new State();
                state.setOpenId(openId);
                state.setDate(date2);
                state.setCorrect(0);
                state.setCount(0);
                state = stateRepository.save(state);
            }

            date1 = state.getDate();
            /*5.判断两次答题时间的间隔，如果间隔超过两分钟，则重新答该关卡的题目*/
            if (Math.abs( date2.getTime() - date1.getTime()) / (1000 * 60) > 2 || state.getCount() == 6) {
                state.setCount(0);
                state.setCorrect(0);
            }
            if (!question.isOnline()) {
                state.setCount(0);
                state.setCorrect(0);
            }
            Integer count = state.getCount();
            Integer right = state.getCorrect();
            /*根据user.getState()来判断单选题、多选题、判断题*/
            boolean b = true;
            if (user.getState() >= 1 && user.getState() <= 5) {
                b = tfngService.judge(question);
            } else if (user.getState() >= 6 && user.getState() <= 10) {
                b = singleChoiceService.judge(question);
            } else if (user.getState() >= 11 && user.getState() <= 15) {
                b = multiChoicesService.judge(question);
            } else {
                return GetResult.fail();
            }
            ++count;
            /*6.判断答题对错*/
            if (!b) {
                msg.setJudge(false);
            } else {

                ++right;
                msg.setJudge(true);
                msg.setSum(right);
            }
            /*7.判断是否闯关成功*/
            if (right == 6) {
                Integer score = user.getScore();
                user.setScore(score+6*5);
                user.setGrade(message.getGrade());
                user.setState(user.getState()+1);
                state.setCorrect(0);
                state.setCount(0);
                msg.setPass(true);
                result.setMsg(message.getSuccess());
            } else if(count == 6 && right < 6){
                state.setCorrect(0);
                state.setCount(0);
                result.setMsg(message.getFailure());
            } else {
                state.setCount(count);
                state.setCorrect(right);
            }

            state.setDate(date2);
            stateRepository.saveAndFlush(state);
            userRepository.save(user);
            result.setData(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

}
